package com.ykc;

import com.alibaba.fastjson.JSON;
import com.ykc.bean.Data;
import com.ykc.bean.Handler;
import com.ykc.bean.Param;
import com.ykc.bean.View;
import com.ykc.helper.BeanHelper;
import com.ykc.helper.ConfigHelper;
import com.ykc.helper.ControllerHelper;
import com.ykc.helper.RequestHelper;
import com.ykc.utils.ReflectionUtil;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.util.Map;

/**
 * @author Ykc
 * @date 2021年05月25日 16:40
 * @description 请求转发器，该Servlet将会在Web容器启动时加载
 */
@WebServlet(urlPatterns = "/*",loadOnStartup = 0)
public class DispatcherServlet extends HttpServlet {

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        //对相关助手类初始化
        HelperLoader.init();

        //获取ServletContext对象, 用于注册Servlet
        ServletContext servletContext=servletConfig.getServletContext();
        //注册处理jsp和静态资源的servlet
        registerServlet(servletContext);
    }

    /*
     * @author Ykc
     * @date 2021/5/25 16:47
     * @param servletContext
     * @description DefaultServlet和JspServlet都是由Web容器创建
     */
    private void registerServlet(ServletContext servletContext) {
        //动态注册处理JSP的Servlet
        ServletRegistration jspServlet=servletContext.getServletRegistration("jsp");
        jspServlet.addMapping(ConfigHelper.getAppJspPath()+"*");

        //动态注册处理静态资源的默认Servlet
        ServletRegistration defaultServlet=servletContext.getServletRegistration("default");
        defaultServlet.addMapping("/favicon.ico");//网站头像
        defaultServlet.addMapping(ConfigHelper.getAppAssetPath()+"*");
    }


    @Override
    public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取请求方法
        String requestMethod=request.getMethod().toUpperCase();
        //获取请求路径
        String requestPath=request.getPathInfo();

        String[] splits=requestPath.split("/");
        if (splits.length>2){
            requestPath="/"+splits[2];
        }

        //根据请求获取处理器（这里类似于SpringMVC中的映射处理器）
        Handler handler= ControllerHelper.getHandler(requestMethod,requestPath);
        if (handler!=null){
            Class<?> controllerClass=handler.getControllerClass();
            Object controllerBean= BeanHelper.getBean(controllerClass);

            //初始化参数
            Param param= RequestHelper.createParam(request);

            //调用与请求对应的方法（这里类似于SpringMVC中的处理器适配器）
            Object result;
            Method actionMethod=handler.getControllerMethod();

            if (param==null||param.isEmpty()){
                result= ReflectionUtil.invokeMethod(controllerBean,actionMethod);
            }else {
                result= ReflectionUtil.invokeMethod(controllerBean,actionMethod,param);
            }

            //跳转页面或返回json数据(这里类似于SpringMVC中的视图解析器)
            if (result instanceof View){
                handleViewResult((View) result,request,response);
            }else if(result instanceof Data){
                handleDataResult((Data) result,response);
            }
        }
    }

    //跳转页面
    private void handleViewResult(View view, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        String path=view.getPath();
        if (StringUtils.isNotEmpty(path)){
            if (path.startsWith("/")){
                response.sendRedirect(request.getContextPath()+path);
            } else {
                //请求转发
                Map<String,Object> model=view.getModel();
                for (Map.Entry<String, Object> entry : model.entrySet()) {
                    request.setAttribute(entry.getKey(), entry.getValue());
                }
                String tmp=ConfigHelper.getAppJspPath();
                request.getRequestDispatcher(tmp+path).forward(request,response);
            }
        }
    }

    //返回JSON数据
    private void handleDataResult(Data data,HttpServletResponse response) throws IOException {
        Object model=data.getModel();
        if (model!=null){
            //设置response的头信息
            response.setContentType("application/json");
            response.setCharacterEncoding("UTF-8");

            //
            PrintWriter writer=response.getWriter();
            String json= JSON.toJSON(model).toString();
            writer.write(json);
            //强制将缓存池中的数据刷出，避免较大内存的数据无法写出
            writer.flush();
            writer.close();
        }
    }
}
